home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume4 / uemacs / part1 next >
Encoding:
Internet Message Format  |  1986-11-30  |  55.0 KB

  1. From: decvax!minow (Martin Minow)
  2. Subject: MicroEmacs (Part 1 of 6)
  3. Newsgroups: mod.sources
  4. Approved: jpn@panda.UUCP
  5.  
  6. Mod.sources:  Volume 4, Issue 68
  7. Submitted by: decvax!minow (Martin Minow)
  8.  
  9. #! /bin/sh
  10. # This is a shell archive, meaning:
  11. # 1. Remove everything above the #! /bin/sh line.
  12. # 2. Save the resulting text in a file.
  13. # 3. Execute the file with /bin/sh (not csh) to create the files:
  14. #    Readme.txt
  15. #    basic.c
  16. #    buffer.c
  17. #    cinfo.c
  18. #    def.h
  19. #    display.c
  20. # This archive created: Sun Apr 13 11:15:10 1986
  21. export PATH; PATH=/bin:$PATH
  22. echo shar: extracting "'Readme.txt'" '(4164 characters)'
  23. if test -f 'Readme.txt'
  24. then
  25.     echo shar: will not over-write existing file "'Readme.txt'"
  26. else
  27. cat << \SHAR_EOF > 'Readme.txt'
  28. This is the only official distribution of MicroEmacs.  Accept no
  29. substitutes.  It is distributed on Usenet on 6 shar archives.
  30. Save them as uemacs1.shar ... uemacs6.shar.
  31.  
  32. Move to .../uemacs and unshar all six source files:
  33.     uemacs[1-3].shar        Editor Mainline
  34.     uemacs4.shar            System-specific sources
  35.     uemacs5.shar            Terminal-specific sources
  36.     uemacs6.shar            Out of date TeX documentation
  37.  
  38. The shar files will automatically create the following directory structure:
  39.  
  40.     .../uemacs            Editor mainline sources
  41.     .../uemacs/sys            System specific sources
  42.     .../uemacs/sys/atari        Atari ST
  43.     .../uemacs/sys/cpm86
  44.     .../uemacs/sys/msdos
  45.     .../uemacs/sys/ultrix        (and other 4.2 bsd Unix systems)
  46.     .../uemacs/sys/vms
  47.     .../uemacs/tty            Terminal handler sources
  48.     .../uemacs/tty/ansi        VT100 and other Ansi-style terminals.
  49.     .../uemacs/tty/atari
  50.     .../uemacs/tty/heath
  51.  
  52. To compile, choose one system, and one tty, and copy the files from the
  53. appropriate subdirectory into the mainline directory.  Then compile all
  54. sources, and link.  The ultrix version includes a Makefile.
  55.  
  56. Unfortunately, the documentation is not yet ready.  You will have
  57. to dig the keypad bindings out of the source code.  Most are setup
  58. in symbol.c, a few might be set in the terminal or system specific
  59. modules.
  60.  
  61. You can get a current keypad binding chart by entering the command
  62.  
  63.     <META>X display-bindings
  64.  
  65. <META> is usually bound to <ESC> or <ALT>.  Here are my possibly
  66. out-of-date bindings.  Note the following abbreviations:
  67.  
  68.     C-<something>        Control-<something>
  69.     M-<something>        Meta -- generally the <ESC> key.
  70.     F10            (etc. -- a keypad function key).
  71.  
  72. Up              back-line
  73. Down            forw-line
  74. Left            back-char
  75. Right           forw-char
  76. Find            search-again
  77. Insert          yank
  78. Remove          kill-region
  79. Select          set-mark
  80. Previous        back-page
  81. Next            forw-page
  82. Help            help
  83. Do              execute-macro
  84. F17             back-window
  85. F18             forw-window
  86. F19             enlarge-window
  87. F20             shrink-window
  88. Rubout          back-del-char
  89. C-@             set-mark
  90. C-A             goto-bol
  91. C-B             back-char
  92. C-C             spawn-cli
  93. C-D             forw-del-char
  94. C-E             goto-eol
  95. C-F             forw-char
  96. C-G             abort
  97. Backspace       back-del-char
  98. C-J             ins-nl-and-indent
  99. C-K             kill-line
  100. C-L             refresh
  101. Return          ins-nl
  102. C-N             forw-line
  103. C-O             ins-nl-and-backup
  104. C-P             back-line
  105. C-Q             quote
  106. C-R             back-i-search
  107. C-S             forw-i-search
  108. C-T             twiddle
  109. C-V             forw-page
  110. C-W             kill-region
  111. C-Y             yank
  112. C-Z             jeff-exit
  113. M-!             reposition-window
  114. M-%             query-replace
  115. M-.             set-mark
  116. M-<             goto-bob
  117. M->             goto-eob
  118. M-B             back-word
  119. M-C             cap-word
  120. M-D             forw-del-word
  121. M-F             forw-word
  122. M-L             lower-word
  123. M-Q             quote
  124. M-R             back-search
  125. M-S             forw-search
  126. M-U             upper-word
  127. M-V             back-page
  128. M-W             copy-region
  129. M-X             extended-command
  130. M-Rubout        back-del-word
  131. C-M-G           abort
  132. M-Backspace     back-del-word
  133. C-M-R           display-message
  134. C-M-V           display-version
  135. C-X (           start-macro
  136. C-X )           end-macro
  137. C-X 1           only-window
  138. C-X 2           split-window
  139. C-X =           display-position
  140. C-X B           use-buffer
  141. C-X E           execute-macro
  142. C-X G           goto-line
  143. C-X K           kill-buffer
  144. C-X N           forw-window
  145. C-X P           back-window
  146. C-X R           back-i-search
  147. C-X S           forw-i-search
  148. C-X Z           enlarge-window
  149. C-X C-B         display-buffers
  150. C-X C-C         quit
  151. C-X C-D         display-directory
  152. C-X C-F         set-file-name
  153. C-X C-G         abort
  154. C-X C-L         lower-region
  155. C-X C-N         down-window
  156. C-X C-O         del-blank-lines
  157. C-X C-P         up-window
  158. C-X C-R         file-read
  159. C-X C-S         file-save
  160. C-X C-U         upper-region
  161. C-X C-V         file-visit
  162. C-X C-W         file-write
  163. C-X C-X         swap-dot-and-mark
  164. C-X C-Z         shrink-window
  165.  
  166. SHAR_EOF
  167. if test 4164 -ne "`wc -c < 'Readme.txt'`"
  168. then
  169.     echo shar: error transmitting "'Readme.txt'" '(should have been 4164 characters)'
  170. fi
  171. fi
  172. echo shar: extracting "'basic.c'" '(7726 characters)'
  173. if test -f 'basic.c'
  174. then
  175.     echo shar: will not over-write existing file "'basic.c'"
  176. else
  177. cat << \SHAR_EOF > 'basic.c'
  178. /*
  179.  * Name:    MicroEMACS
  180.  *        Basic cursor motion commands.
  181.  * Version:    29
  182.  * Last edit:    05-Feb-86
  183.  * By:        rex::conroy
  184.  *        decvax!decwrl!dec-rhea!dec-rex!conroy
  185.  *
  186.  * The routines in this file are the basic
  187.  * command functions for moving the cursor around on
  188.  * the screen, setting mark, and swapping dot with
  189.  * mark. Only moves between lines, which might make the
  190.  * current buffer framing bad, are hard.
  191.  */
  192. #include    "def.h"
  193.  
  194. /*
  195.  * Go to beginning of line.
  196.  */
  197. gotobol(f, n, k)
  198. {
  199.     curwp->w_doto  = 0;
  200.     return (TRUE);
  201. }
  202.  
  203. /*
  204.  * Move cursor backwards. Do the
  205.  * right thing if the count is less than
  206.  * 0. Error if you try to move back from
  207.  * the beginning of the buffer.
  208.  */
  209. backchar(f, n, k)
  210. register int    n;
  211. {
  212.     register LINE    *lp;
  213.  
  214.     if (n < 0)
  215.         return (forwchar(f, -n, KRANDOM));
  216.     while (n--) {
  217.         if (curwp->w_doto == 0) {
  218.             if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
  219.                 return (FALSE);
  220.             curwp->w_dotp  = lp;
  221.             curwp->w_doto  = llength(lp);
  222.             curwp->w_flag |= WFMOVE;
  223.         } else
  224.             curwp->w_doto--;
  225.     }
  226.     return (TRUE);
  227. }
  228.  
  229. /*
  230.  * Go to end of line.
  231.  */
  232. gotoeol(f, n, k)
  233. {
  234.     curwp->w_doto  = llength(curwp->w_dotp);
  235.     return (TRUE);
  236. }
  237.  
  238. /*
  239.  * Move cursor forwards. Do the
  240.  * right thing if the count is less than
  241.  * 0. Error if you try to move forward
  242.  * from the end of the buffer.
  243.  */
  244. forwchar(f, n, k)
  245. register int    n;
  246. {
  247.     if (n < 0)
  248.         return (backchar(f, -n, KRANDOM));
  249.     while (n--) {
  250.         if (curwp->w_doto == llength(curwp->w_dotp)) {
  251.             if (curwp->w_dotp == curbp->b_linep)
  252.                 return (FALSE);
  253.             curwp->w_dotp  = lforw(curwp->w_dotp);
  254.             curwp->w_doto  = 0;
  255.             curwp->w_flag |= WFMOVE;
  256.         } else
  257.             curwp->w_doto++;
  258.     }
  259.     return (TRUE);
  260. }
  261.  
  262. /*
  263.  * Go to the beginning of the
  264.  * buffer. Setting WFHARD is conservative,
  265.  * but almost always the case.
  266.  */
  267. gotobob(f, n, k)
  268. {
  269.     curwp->w_dotp  = lforw(curbp->b_linep);
  270.     curwp->w_doto  = 0;
  271.     curwp->w_flag |= WFHARD;
  272.     return (TRUE);
  273. }
  274.  
  275. /*
  276.  * Go to the end of the buffer.
  277.  * Setting WFHARD is conservative, but
  278.  * almost always the case.
  279.  */
  280. gotoeob(f, n, k)
  281. {
  282.     curwp->w_dotp  = curbp->b_linep;
  283.     curwp->w_doto  = 0;
  284.     curwp->w_flag |= WFHARD;
  285.     return (TRUE);
  286. }
  287.  
  288. /*
  289.  * Move forward by full lines.
  290.  * If the number of lines to move is less
  291.  * than zero, call the backward line function to
  292.  * actually do it. The last command controls how
  293.  * the goal column is set.
  294.  */
  295. forwline(f, n, k)
  296. {
  297.     register LINE    *dlp;
  298.  
  299.     if (n < 0)
  300.         return (backline(f, -n, KRANDOM));
  301.     if ((lastflag&CFCPCN) == 0)        /* Fix goal.        */
  302.         setgoal();
  303.     thisflag |= CFCPCN;
  304.     dlp = curwp->w_dotp;
  305.     while (n-- && dlp!=curbp->b_linep)
  306.         dlp = lforw(dlp);
  307.     curwp->w_dotp  = dlp;
  308.     curwp->w_doto  = getgoal(dlp);
  309.     curwp->w_flag |= WFMOVE;
  310.     return (TRUE);
  311. }
  312.  
  313. /*
  314.  * This function is like "forwline", but
  315.  * goes backwards. The scheme is exactly the same.
  316.  * Check for arguments that are less than zero and
  317.  * call your alternate. Figure out the new line and
  318.  * call "movedot" to perform the motion.
  319.  */
  320. backline(f, n, k)
  321. {
  322.     register LINE    *dlp;
  323.  
  324.     if (n < 0)
  325.         return (forwline(f, -n, KRANDOM));
  326.     if ((lastflag&CFCPCN) == 0)        /* Fix goal.        */
  327.         setgoal();
  328.     thisflag |= CFCPCN;
  329.     dlp = curwp->w_dotp;
  330.     while (n-- && lback(dlp)!=curbp->b_linep)
  331.         dlp = lback(dlp);
  332.     curwp->w_dotp  = dlp;
  333.     curwp->w_doto  = getgoal(dlp);
  334.     curwp->w_flag |= WFMOVE;
  335.     return (TRUE);
  336. }
  337.  
  338. /*
  339.  * Set the current goal column,
  340.  * which is saved in the external variable "curgoal",
  341.  * to the current cursor column. The column is never off
  342.  * the edge of the screen; it's more like display then
  343.  * show position.
  344.  */
  345. setgoal()
  346. {
  347.     register int    c;
  348.     register int    i;
  349.  
  350.     curgoal = 0;                /* Get the position.    */
  351.     for (i=0; i<curwp->w_doto; ++i) {
  352.         c = lgetc(curwp->w_dotp, i);
  353.         if (c == '\t')
  354.             curgoal |= 0x07;
  355.         else if (ISCTRL(c) != FALSE)
  356.             ++curgoal;
  357.         ++curgoal;
  358.     }
  359.     if (curgoal >= ncol)            /* Chop to tty width.    */
  360.         curgoal = ncol-1;
  361. }
  362.  
  363. /*
  364.  * This routine looks at a line (pointed
  365.  * to by the LINE pointer "dlp") and the current
  366.  * vertical motion goal column (set by the "setgoal"
  367.  * routine above) and returns the best offset to use
  368.  * when a vertical motion is made into the line.
  369.  */
  370. getgoal(dlp)
  371. register LINE    *dlp;
  372. {
  373.     register int    c;
  374.     register int    col;
  375.     register int    newcol;
  376.     register int    dbo;
  377.  
  378.     col = 0;
  379.     dbo = 0;
  380.     while (dbo != llength(dlp)) {
  381.         c = lgetc(dlp, dbo);
  382.         newcol = col;
  383.         if (c == '\t')
  384.             newcol |= 0x07;
  385.         else if (ISCTRL(c) != FALSE)
  386.             ++newcol;
  387.         ++newcol;
  388.         if (newcol > curgoal)
  389.             break;
  390.         col = newcol;
  391.         ++dbo;
  392.     }
  393.     return (dbo);
  394. }
  395.  
  396. /*
  397.  * Scroll forward by a specified number
  398.  * of lines, or by a full page if no argument.
  399.  * The "2" is the window overlap (this is the default
  400.  * value from ITS EMACS). Because the top line in
  401.  * the window is zapped, we have to do a hard
  402.  * update and get it back.
  403.  */
  404. forwpage(f, n, k)
  405. register int    n;
  406. {
  407.     register LINE    *lp;
  408.  
  409.     if (f == FALSE) {
  410.         n = curwp->w_ntrows - 2;    /* Default scroll.    */
  411.         if (n <= 0)            /* Forget the overlap    */
  412.             n = 1;            /* if tiny window.    */
  413.     } else if (n < 0)
  414.         return (backpage(f, -n, KRANDOM));
  415. #if    CVMVAS
  416.     else                    /* Convert from pages    */
  417.         n *= curwp->w_ntrows;        /* to lines.        */
  418. #endif
  419.     lp = curwp->w_linep;
  420.     while (n-- && lp!=curbp->b_linep)
  421.         lp = lforw(lp);
  422.     curwp->w_linep = lp;
  423.     curwp->w_dotp  = lp;
  424.     curwp->w_doto  = 0;
  425.     curwp->w_flag |= WFHARD;
  426.     return (TRUE);
  427. }
  428.  
  429. /*
  430.  * This command is like "forwpage",
  431.  * but it goes backwards. The "2", like above,
  432.  * is the overlap between the two windows. The
  433.  * value is from the ITS EMACS manual. The
  434.  * hard update is done because the top line in
  435.  * the window is zapped.
  436.  */
  437. backpage(f, n, k)
  438. register int    n;
  439. {
  440.     register LINE    *lp;
  441.  
  442.     if (f == FALSE) {
  443.         n = curwp->w_ntrows - 2;    /* Default scroll.    */
  444.         if (n <= 0)            /* Don't blow up if the    */
  445.             n = 1;            /* window is tiny.    */
  446.     } else if (n < 0)
  447.         return (forwpage(f, -n, KRANDOM));
  448. #if    CVMVAS
  449.     else                    /* Convert from pages    */
  450.         n *= curwp->w_ntrows;        /* to lines.        */
  451. #endif
  452.     lp = curwp->w_linep;
  453.     while (n-- && lback(lp)!=curbp->b_linep)
  454.         lp = lback(lp);
  455.     curwp->w_linep = lp;
  456.     curwp->w_dotp  = lp;
  457.     curwp->w_doto  = 0;
  458.     curwp->w_flag |= WFHARD;
  459.     return (TRUE);
  460. }
  461.  
  462. /*
  463.  * Set the mark in the current window
  464.  * to the value of dot. A message is written to
  465.  * the echo line unless we are running in a keyboard
  466.  * macro, when it would be silly.
  467.  */
  468. setmark(f, n, k)
  469. {
  470.     curwp->w_markp = curwp->w_dotp;
  471.     curwp->w_marko = curwp->w_doto;
  472.     if (kbdmop == NULL)
  473.         eprintf("[Mark set]");
  474.     return (TRUE);
  475. }
  476.  
  477. /*
  478.  * Swap the values of "dot" and "mark" in
  479.  * the current window. This is pretty easy, because
  480.  * all of the hard work gets done by the standard routine
  481.  * that moves the mark about. The only possible
  482.  * error is "no mark".
  483.  */
  484. swapmark(f, n, k)
  485. {
  486.     register LINE    *odotp;
  487.     register int    odoto;
  488.  
  489.     if (curwp->w_markp == NULL) {
  490.         eprintf("No mark in this window");
  491.         return (FALSE);
  492.     }
  493.     odotp = curwp->w_dotp;
  494.     odoto = curwp->w_doto;
  495.     curwp->w_dotp  = curwp->w_markp;
  496.     curwp->w_doto  = curwp->w_marko;
  497.     curwp->w_markp = odotp;
  498.     curwp->w_marko = odoto;
  499.     curwp->w_flag |= WFMOVE;
  500.     return (TRUE);
  501. }
  502.  
  503. /*
  504.  * Go to a specific line, mostly for
  505.  * looking up errors in C programs, which give the
  506.  * error a line number. If an argument is present, then
  507.  * it is the line number, else prompt for a line number
  508.  * to use.
  509.  */
  510. gotoline(f, n, k)
  511. register int    n;
  512. {
  513.     register LINE    *clp;
  514.     register int    s;
  515.     char        buf[32];
  516.  
  517.     if (f == FALSE) {
  518.         if ((s=ereply("Goto line: ", buf, sizeof(buf))) != TRUE)
  519.             return (s);
  520.         n = atoi(buf);
  521.     }
  522.     if (n <= 0) {
  523.         eprintf("Bad line");
  524.         return (FALSE);
  525.     }
  526.     clp = lforw(curbp->b_linep);        /* "clp" is first line    */
  527.     while (n != 1) {
  528.         if (clp == curbp->b_linep) {
  529.             eprintf("Line number too large");
  530.             return (FALSE);
  531.         }
  532.         clp = lforw(clp);
  533.         --n;
  534.     }
  535.     curwp->w_dotp = clp;
  536.     curwp->w_doto = 0;
  537.     curwp->w_flag |= WFMOVE;
  538.     return (TRUE);
  539. }
  540. SHAR_EOF
  541. if test 7726 -ne "`wc -c < 'basic.c'`"
  542. then
  543.     echo shar: error transmitting "'basic.c'" '(should have been 7726 characters)'
  544. fi
  545. fi
  546. echo shar: extracting "'buffer.c'" '(8922 characters)'
  547. if test -f 'buffer.c'
  548. then
  549.     echo shar: will not over-write existing file "'buffer.c'"
  550. else
  551. cat << \SHAR_EOF > 'buffer.c'
  552. /*
  553.  * Name:    MicroEMACS
  554.  *        Buffer handling.
  555.  * Version:    30
  556.  * Last edit:    17-Feb-86
  557.  * By:        rex::conroy
  558.  *        decvax!decwrl!dec-rhea!dec-rex!conroy
  559.  */
  560. #include    "def.h"
  561.  
  562. /*
  563.  * Attach a buffer to a window. The
  564.  * values of dot and mark come from the buffer
  565.  * if the use count is 0. Otherwise, they come
  566.  * from some other window.
  567.  */
  568. usebuffer(f, n, k)
  569. {
  570.     register BUFFER    *bp;
  571.     register WINDOW    *wp;
  572.     register int    s;
  573.     char        bufn[NBUFN];
  574.  
  575.     if ((s=ereply("Use buffer: ", bufn, NBUFN)) != TRUE)
  576.         return (s);
  577.     if ((bp=bfind(bufn, TRUE)) == NULL)
  578.         return (FALSE);
  579.     if (--curbp->b_nwnd == 0) {        /* Last use.        */
  580.         curbp->b_dotp  = curwp->w_dotp;
  581.         curbp->b_doto  = curwp->w_doto;
  582.         curbp->b_markp = curwp->w_markp;
  583.         curbp->b_marko = curwp->w_marko;
  584.     }
  585.     curbp = bp;                /* Switch.        */
  586.     curwp->w_bufp  = bp;
  587.     curwp->w_linep = bp->b_linep;        /* For macros, ignored.    */
  588.     curwp->w_flag |= WFMODE|WFFORCE|WFHARD;    /* Quite nasty.        */
  589.     if (bp->b_nwnd++ == 0) {        /* First use.        */
  590.         curwp->w_dotp  = bp->b_dotp;
  591.         curwp->w_doto  = bp->b_doto;
  592.         curwp->w_markp = bp->b_markp;
  593.         curwp->w_marko = bp->b_marko;
  594.         return (TRUE);
  595.     }
  596.     wp = wheadp;                /* Look for old.    */
  597.     while (wp != NULL) {
  598.         if (wp!=curwp && wp->w_bufp==bp) {
  599.             curwp->w_dotp  = wp->w_dotp;
  600.             curwp->w_doto  = wp->w_doto;
  601.             curwp->w_markp = wp->w_markp;
  602.             curwp->w_marko = wp->w_marko;
  603.             break;
  604.         }
  605.         wp = wp->w_wndp;
  606.     }
  607.     return (TRUE);
  608. }
  609.  
  610. /*
  611.  * Dispose of a buffer, by name.
  612.  * Ask for the name. Look it up (don't get too
  613.  * upset if it isn't there at all!). Get quite upset
  614.  * if the buffer is being displayed. Clear the buffer (ask
  615.  * if the buffer has been changed). Then free the header
  616.  * line and the buffer header. Bound to "C-X K".
  617.  */
  618. killbuffer(f, n, k)
  619. {
  620.     register BUFFER    *bp;
  621.     register BUFFER    *bp1;
  622.     register BUFFER    *bp2;
  623.     register int    s;
  624.     char        bufn[NBUFN];
  625.  
  626.     if ((s=ereply("Kill buffer: ", bufn, NBUFN)) != TRUE)
  627.         return (s);
  628.     if ((bp=bfind(bufn, FALSE)) == NULL)    /* Easy if unknown.    */
  629.         return (TRUE);
  630.     if (bp->b_nwnd != 0) {            /* Error if on screen.    */
  631.         eprintf("Buffer is being displayed");
  632.         return (FALSE);
  633.     }
  634.     if ((s=bclear(bp)) != TRUE)        /* Blow text away.    */
  635.         return (s);
  636.     free((char *) bp->b_linep);        /* Release header line.    */
  637.     bp1 = NULL;                /* Find the header.    */
  638.     bp2 = bheadp;
  639.     while (bp2 != bp) {
  640.         bp1 = bp2;
  641.         bp2 = bp2->b_bufp;
  642.     }
  643.     bp2 = bp2->b_bufp;            /* Next one in chain.    */
  644.     if (bp1 == NULL)            /* Unlink it.        */
  645.         bheadp = bp2;
  646.     else
  647.         bp1->b_bufp = bp2;
  648.     free((char *) bp);            /* Release buffer block    */
  649.     return (TRUE);
  650. }
  651.  
  652. /*
  653.  * Display the buffer list. This is done
  654.  * in two parts. The "makelist" routine figures out
  655.  * the text, and puts it in the buffer whoses header is
  656.  * pointed to by the external "blistp". The "popblist"
  657.  * then pops the data onto the screen. Bound to
  658.  * "C-X C-B".
  659.  */
  660. listbuffers(f, n, k)
  661. {
  662.     register int    s;
  663.  
  664.     if ((s=makelist()) != TRUE)
  665.         return (s);
  666.     return (popblist());
  667. }
  668.  
  669. /*
  670.  * Pop the special buffer whose
  671.  * buffer header is pointed to by the external
  672.  * variable "blistp" onto the screen. This is used
  673.  * by the "listbuffers" routine (above) and by
  674.  * some other packages. Returns a status.
  675.  */
  676. popblist()
  677. {
  678.     register WINDOW    *wp;
  679.     register BUFFER    *bp;
  680.  
  681.     if (blistp->b_nwnd == 0) {        /* Not on screen yet.    */
  682.         if ((wp=wpopup()) == NULL)
  683.             return (FALSE);
  684.         bp = wp->w_bufp;
  685.         if (--bp->b_nwnd == 0) {
  686.             bp->b_dotp  = wp->w_dotp;
  687.             bp->b_doto  = wp->w_doto;
  688.             bp->b_markp = wp->w_markp;
  689.             bp->b_marko = wp->w_marko;
  690.         }
  691.         wp->w_bufp  = blistp;
  692.         ++blistp->b_nwnd;
  693.     }
  694.     wp = wheadp;
  695.     while (wp != NULL) {
  696.         if (wp->w_bufp == blistp) {
  697.             wp->w_linep = lforw(blistp->b_linep);
  698.             wp->w_dotp  = lforw(blistp->b_linep);
  699.             wp->w_doto  = 0;
  700.             wp->w_markp = NULL;
  701.             wp->w_marko = 0;
  702.             wp->w_flag |= WFMODE|WFHARD;
  703.         }
  704.         wp = wp->w_wndp;
  705.     }
  706.     return (TRUE);
  707. }
  708.  
  709. /*
  710.  * This routine rebuilds the
  711.  * text in the special secret buffer
  712.  * that holds the buffer list. It is called
  713.  * by the list buffers command. Return TRUE
  714.  * if everything works. Return FALSE if there
  715.  * is an error (if there is no memory).
  716.  */
  717. makelist()
  718. {
  719.     register char    *cp1;
  720.     register char    *cp2;
  721.     register int    c;
  722.     register BUFFER    *bp;
  723.     register LINE    *lp;
  724.     register int    nbytes;
  725.     register int    s;
  726.     char        b[6+1];
  727.     char        line[128];
  728.  
  729.     blistp->b_flag &= ~BFCHG;        /* Blow away old.    */
  730.     if ((s=bclear(blistp)) != TRUE)
  731.         return (s);
  732.     strcpy(blistp->b_fname, "");
  733.     if (addline("C   Size Buffer           File") == FALSE
  734.     ||  addline("-   ---- ------           ----") == FALSE)
  735.         return (FALSE);
  736.     bp = bheadp;                /* For all buffers    */
  737.     while (bp != NULL) {
  738.         cp1 = &line[0];            /* Start at left edge    */
  739.         if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed    */
  740.             *cp1++ = '*';
  741.         else
  742.             *cp1++ = ' ';
  743.         *cp1++ = ' ';            /* Gap.            */
  744.         nbytes = 0;            /* Count bytes in buf.    */
  745.         lp = lforw(bp->b_linep);
  746.         while (lp != bp->b_linep) {
  747.             nbytes += llength(lp)+1;
  748.             lp = lforw(lp);
  749.         }
  750.         itoa(b, 6, nbytes);        /* 6 digit buffer size.    */
  751.         cp2 = &b[0];
  752.         while ((c = *cp2++) != 0)
  753.             *cp1++ = c;
  754.         *cp1++ = ' ';            /* Gap.            */
  755.         cp2 = &bp->b_bname[0];        /* Buffer name        */
  756.         while ((c = *cp2++) != 0)
  757.             *cp1++ = c;
  758.         cp2 = &bp->b_fname[0];        /* File name        */
  759.         if (*cp2 != 0) {
  760.             while (cp1 < &line[1+1+6+1+NBUFN+1])
  761.                 *cp1++ = ' ';        
  762.             while ((c = *cp2++) != 0) {
  763.                 if (cp1 < &line[128-1])
  764.                     *cp1++ = c;
  765.             }
  766.         }
  767.         *cp1 = 0;            /* Add to the buffer.    */
  768.         if (addline(line) == FALSE)
  769.             return (FALSE);
  770.         bp = bp->b_bufp;
  771.     }
  772.     return (TRUE);                /* All done        */
  773. }
  774.  
  775. /*
  776.  * Used above.
  777.  */
  778. itoa(buf, width, num)
  779. register char    buf[];
  780. register int    width;
  781. register int    num;
  782. {
  783.     buf[width] = 0;                /* End of string.    */
  784.     while (num >= 10) {            /* Conditional digits.    */
  785.         buf[--width] = (num%10) + '0';
  786.         num /= 10;
  787.     }
  788.     buf[--width] = num + '0';        /* Always 1 digit.    */
  789.     while (width != 0)            /* Pad with blanks.    */
  790.         buf[--width] = ' ';
  791. }
  792.  
  793. /*
  794.  * The argument "text" points to
  795.  * a string. Append this line to the
  796.  * buffer list buffer. Handcraft the EOL
  797.  * on the end. Return TRUE if it worked and
  798.  * FALSE if you ran out of room.
  799.  */
  800. addline(text)
  801. char    *text;
  802. {
  803.     register LINE    *lp;
  804.     register int    i;
  805.     register int    ntext;
  806.  
  807.     ntext = strlen(text);
  808.     if ((lp=lalloc(ntext)) == NULL)
  809.         return (FALSE);
  810.     for (i=0; i<ntext; ++i)
  811.         lputc(lp, i, text[i]);
  812.     blistp->b_linep->l_bp->l_fp = lp;    /* Hook onto the end    */
  813.     lp->l_bp = blistp->b_linep->l_bp;
  814.     blistp->b_linep->l_bp = lp;
  815.     lp->l_fp = blistp->b_linep;
  816.     if (blistp->b_dotp == blistp->b_linep)    /* If "." is at the end    */
  817.         blistp->b_dotp = lp;        /* move it to new line    */
  818.     return (TRUE);
  819. }
  820.  
  821. /*
  822.  * Look through the list of
  823.  * buffers. Return TRUE if there
  824.  * are any changed buffers. Special buffers
  825.  * like the buffer list buffer don't count, as
  826.  * they are not in the list. Return FALSE if
  827.  * there are no changed buffers.
  828.  */
  829. anycb()
  830. {
  831.     register BUFFER    *bp;
  832.  
  833.     bp = bheadp;
  834.     while (bp != NULL) {
  835.         if ((bp->b_flag&BFCHG) != 0)
  836.             return (TRUE);
  837.         bp = bp->b_bufp;
  838.     }
  839.     return (FALSE);
  840. }
  841.  
  842. /*
  843.  * Search for a buffer, by name.
  844.  * If not found, and the "cflag" is TRUE,
  845.  * create a buffer and put it in the list of
  846.  * all buffers. Return pointer to the BUFFER
  847.  * block for the buffer.
  848.  */
  849. BUFFER    *
  850. bfind(bname, cflag)
  851. register char    *bname;
  852. {
  853.     register BUFFER    *bp;
  854.  
  855.     bp = bheadp;
  856.     while (bp != NULL) {
  857.         if (strcmp(bname, bp->b_bname) == 0)
  858.             return (bp);
  859.         bp = bp->b_bufp;
  860.     }
  861.     if (cflag!=FALSE && (bp=bcreate(bname))!=NULL) {
  862.         bp->b_bufp = bheadp;
  863.         bheadp = bp;
  864.     }
  865.     return (bp);
  866. }
  867.  
  868. /*
  869.  * Create a buffer, by name.
  870.  * Return a pointer to the BUFFER header
  871.  * block, or NULL if the buffer cannot
  872.  * be created. The BUFFER is not put in the
  873.  * list of all buffers; this is called by
  874.  * "edinit" to create the buffer list
  875.  * buffer.
  876.  */
  877. BUFFER    *
  878. bcreate(bname)
  879. register char    *bname;
  880. {
  881.     register BUFFER    *bp;
  882.     register LINE    *lp;
  883.  
  884.     if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
  885.         return (NULL);
  886.     if ((lp=lalloc(0)) == NULL) {
  887.         free((char *) bp);
  888.         return (NULL);
  889.     }
  890.     bp->b_bufp  = NULL;
  891.     bp->b_dotp  = lp;
  892.     bp->b_doto  = 0;
  893.     bp->b_markp = NULL;
  894.     bp->b_marko = 0;
  895.     bp->b_flag  = 0;
  896.     bp->b_nwnd  = 0;
  897.     bp->b_linep = lp;
  898.     strcpy(bp->b_fname, "");
  899.     strcpy(bp->b_bname, bname);
  900.     lp->l_fp = lp;
  901.     lp->l_bp = lp;
  902.     return (bp);
  903. }
  904.  
  905. /*
  906.  * This routine blows away all of the text
  907.  * in a buffer. If the buffer is marked as changed
  908.  * then we ask if it is ok to blow it away; this is
  909.  * to save the user the grief of losing text. The
  910.  * window chain is nearly always wrong if this gets
  911.  * called; the caller must arrange for the updates
  912.  * that are required. Return TRUE if everything
  913.  * looks good.
  914.  */
  915. bclear(bp)
  916. register BUFFER    *bp;
  917. {
  918.     register LINE    *lp;
  919.     register int    s;
  920.     
  921.     if ((bp->b_flag&BFCHG) != 0        /* Changed.        */
  922.     && (s=eyesno("Discard changes")) != TRUE)
  923.         return (s);
  924.     bp->b_flag  &= ~BFCHG;            /* Not changed        */
  925.     while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  926.         lfree(lp);
  927.     bp->b_dotp  = bp->b_linep;        /* Fix "."        */
  928.     bp->b_doto  = 0;
  929.     bp->b_markp = NULL;            /* Invalidate "mark"    */
  930.     bp->b_marko = 0;
  931.     return (TRUE);
  932. }
  933. SHAR_EOF
  934. if test 8922 -ne "`wc -c < 'buffer.c'`"
  935. then
  936.     echo shar: error transmitting "'buffer.c'" '(should have been 8922 characters)'
  937. fi
  938. fi
  939. echo shar: extracting "'cinfo.c'" '(2394 characters)'
  940. if test -f 'cinfo.c'
  941. then
  942.     echo shar: will not over-write existing file "'cinfo.c'"
  943. else
  944. cat << \SHAR_EOF > 'cinfo.c'
  945. /*
  946.  * Name:    MicroEMACS
  947.  *        Character class tables.
  948.  * Version:    29
  949.  * Last edit:    05-Feb-86
  950.  * By:        rex::conroy
  951.  *        decvax!decwrl!dec-rhea!dec-rex!conroy
  952.  *
  953.  * Do it yourself character classification
  954.  * macros, that understand the multinational character set,
  955.  * and let me ask some questions the standard macros (in
  956.  * ctype.h) don't let you ask.
  957.  */
  958. #include    "def.h"
  959.  
  960. /*
  961.  * This table, indexed by a character drawn
  962.  * from the 256 member character set, is used by my
  963.  * own character type macros to answer questions about the
  964.  * type of a character. It handles the full multinational
  965.  * character set, and lets me ask some questions that the
  966.  * standard "ctype" macros cannot ask.
  967.  */
  968. char    cinfo[256] = {
  969.     _C,        _C,        _C,        _C,    /* 0x0X    */
  970.     _C,        _C,        _C,        _C,
  971.     _C,        _C,        _C,        _C,
  972.     _C,        _C,        _C,        _C,
  973.     _C,        _C,        _C,        _C,    /* 0x1X    */
  974.     _C,        _C,        _C,        _C,
  975.     _C,        _C,        _C,        _C,
  976.     _C,        _C,        _C,        _C,
  977.     0,        0,        0,        0,    /* 0x2X    */
  978.     _W,        0,        0,        _W,
  979.     0,        0,        0,        0,
  980.     0,        0,        0,        0,
  981.     _W,        _W,        _W,        _W,    /* 0x3X    */
  982.     _W,        _W,        _W,        _W,
  983.     _W,        _W,        0,        0,
  984.     0,        0,        0,        0,
  985.     0,        _U|_W,        _U|_W,        _U|_W,    /* 0x4X    */
  986.     _U|_W,        _U|_W,        _U|_W,        _U|_W,
  987.     _U|_W,        _U|_W,        _U|_W,        _U|_W,
  988.     _U|_W,        _U|_W,        _U|_W,        _U|_W,
  989.     _U|_W,        _U|_W,        _U|_W,        _U|_W,    /* 0x5X    */
  990.     _U|_W,        _U|_W,        _U|_W,        _U|_W,
  991.     _U|_W,        _U|_W,        _U|_W,        0,
  992.     0,        0,        0,        _W,
  993.     0,        _L|_W,        _L|_W,        _L|_W,    /* 0x6X    */
  994.     _L|_W,        _L|_W,        _L|_W,        _L|_W,
  995.     _L|_W,        _L|_W,        _L|_W,        _L|_W,
  996.     _L|_W,        _L|_W,        _L|_W,        _L|_W,
  997.     _L|_W,        _L|_W,        _L|_W,        _L|_W,    /* 0x7X    */
  998.     _L|_W,        _L|_W,        _L|_W,        _L|_W,
  999.     _L|_W,        _L|_W,        _L|_W,        0,
  1000.     0,        0,        0,        _C,
  1001.     0,        0,        0,        0,    /* 0x8X    */
  1002.     0,        0,        0,        0,
  1003.     0,        0,        0,        0,
  1004.     0,        0,        0,        0,
  1005.     0,        0,        0,        0,    /* 0x9X    */
  1006.     0,        0,        0,        0,
  1007.     0,        0,        0,        0,
  1008.     0,        0,        0,        0,
  1009.     0,        0,        0,        0,    /* 0xAX    */
  1010.     0,        0,        0,        0,
  1011.     0,        0,        0,        0,
  1012.     0,        0,        0,        0,
  1013.     0,        0,        0,        0,    /* 0xBX    */
  1014.     0,        0,        0,        0,
  1015.     0,        0,        0,        0,
  1016.     0,        0,        0,        0,
  1017.     _U|_W,        _U|_W,        _U|_W,        _U|_W,    /* 0xCX    */
  1018.     _U|_W,        _U|_W,        _U|_W,        _U|_W,
  1019.     _U|_W,        _U|_W,        _U|_W,        _U|_W,
  1020.     _U|_W,        _U|_W,        _U|_W,        _U|_W,
  1021.     0,        _U|_W,        _U|_W,        _U|_W,    /* 0xDX    */
  1022.     _U|_W,        _U|_W,        _U|_W,        _U|_W,
  1023.     _U|_W,        _U|_W,        _U|_W,        _U|_W,
  1024.     _U|_W,        _U|_W,        0,        _W,
  1025.     _L|_W,        _L|_W,        _L|_W,        _L|_W,    /* 0xEX    */
  1026.     _L|_W,        _L|_W,        _L|_W,        _L|_W,
  1027.     _L|_W,        _L|_W,        _L|_W,        _L|_W,
  1028.     _L|_W,        _L|_W,        _L|_W,        _L|_W,
  1029.     0,        _L|_W,        _L|_W,        _L|_W,    /* 0xFX    */
  1030.     _L|_W,        _L|_W,        _L|_W,        _L|_W,
  1031.     _L|_W,        _L|_W,        _L|_W,        _L|_W,
  1032.     _L|_W,        _L|_W,        0,        0
  1033. };
  1034. SHAR_EOF
  1035. if test 2394 -ne "`wc -c < 'cinfo.c'`"
  1036. then
  1037.     echo shar: error transmitting "'cinfo.c'" '(should have been 2394 characters)'
  1038. fi
  1039. fi
  1040. echo shar: extracting "'def.h'" '(10999 characters)'
  1041. if test -f 'def.h'
  1042. then
  1043.     echo shar: will not over-write existing file "'def.h'"
  1044. else
  1045. cat << \SHAR_EOF > 'def.h'
  1046. /*
  1047.  * Name:    MicroEMACS
  1048.  *        Common header file.
  1049.  * Version:    29
  1050.  * Last edit:    14-Feb-86
  1051.  * By:        rex::conroy
  1052.  *        decvax!decwrl!dec-rhea!dec-rex!conroy
  1053.  * 
  1054.  * This file is the general header file for all parts
  1055.  * of the MicroEMACS display editor. It contains all of the
  1056.  * general definitions and macros. It also contains some
  1057.  * conditional compilation flags. All of the per-system and
  1058.  * per-terminal definitions are in special header files.
  1059.  * The most common reason to edit this file would be to zap
  1060.  * the definition of CVMVAS or BACKUP.
  1061.  */
  1062. #include    "sysdef.h"        /* Order is critical.        */
  1063. #include    "ttydef.h"
  1064. #include    <stdio.h>
  1065.  
  1066. #define    CVMVAS    1            /* C-V, M-V work in pages.    */
  1067. #define    BACKUP    0            /* Make backup file.        */
  1068.  
  1069. /*
  1070.  * Table sizes, etc.
  1071.  */
  1072. #define    NSHASH    31            /* Symbol table hash size.    */
  1073. #define    NFILEN    80            /* Length, file name.        */
  1074. #define    NBUFN    16            /* Length, buffer name.        */
  1075. #define    NLINE    256            /* Length, line.        */
  1076. #define    NKBDM    256            /* Length, keyboard macro.    */
  1077. #define NMSG    512            /* Length, message buffer.    */
  1078. #define    NPAT    80            /* Length, pattern.        */
  1079. #define    HUGE    1000            /* A rather large number.    */
  1080. #define NSRCH    128            /* Undoable search commands.    */
  1081. #define    NXNAME    64            /* Length, extended command.    */
  1082.  
  1083. /*
  1084.  * Universal.
  1085.  */
  1086. #define    FALSE    0            /* False, no, bad, etc.        */
  1087. #define    TRUE    1            /* True, yes, good, etc.    */
  1088. #define    ABORT    2            /* Death, ^G, abort, etc.    */
  1089.  
  1090. /*
  1091.  * These flag bits keep track of
  1092.  * some aspects of the last command. The CFCPCN
  1093.  * flag controls goal column setting. The CFKILL
  1094.  * flag controls the clearing versus appending
  1095.  * of data in the kill buffer.
  1096.  */
  1097. #define    CFCPCN    0x0001            /* Last command was C-P, C-N    */
  1098. #define    CFKILL    0x0002            /* Last command was a kill    */
  1099.  
  1100. /*
  1101.  * File I/O.
  1102.  */
  1103. #define    FIOSUC    0            /* Success.            */
  1104. #define    FIOFNF    1            /* File not found.        */
  1105. #define    FIOEOF    2            /* End of file.            */
  1106. #define    FIOERR    3            /* Error.            */
  1107.  
  1108. /*
  1109.  * Directory I/O.
  1110.  */
  1111. #define    DIOSUC    0            /* Success.            */
  1112. #define    DIOEOF    1            /* End of file.            */
  1113. #define    DIOERR    2            /* Error.            */
  1114.  
  1115. /*
  1116.  * Display colors.
  1117.  */
  1118. #define    CNONE    0            /* Unknown color.        */
  1119. #define    CTEXT    1            /* Text color.            */
  1120. #define    CMODE    2            /* Mode line color.        */
  1121.  
  1122. /*
  1123.  * Flags for "eread".
  1124.  */
  1125. #define    EFNEW    0x0001            /* New prompt.            */
  1126. #define    EFAUTO    0x0002            /* Autocompletion enabled.    */
  1127. #define    EFCR    0x0004            /* Echo CR at end; last read.    */
  1128.  
  1129. /*
  1130.  * Keys are represented inside using an 11 bit
  1131.  * keyboard code. The transformation between the keys on
  1132.  * the keyboard and 11 bit code is done by terminal specific
  1133.  * code in the "kbd.c" file. The actual character is stored
  1134.  * in 8 bits (DEC multinationals work); there is also a control
  1135.  * flag KCTRL, a meta flag KMETA, and a control-X flag KCTLX.
  1136.  * ASCII control characters are always represented using the
  1137.  * KCTRL form. Although the C0 control set is free, it is
  1138.  * reserved for C0 controls because it makes the communication
  1139.  * between "getkey" and "getkbd" easier. The funny keys get
  1140.  * mapped into the C1 control area.
  1141.  */
  1142. #define    NKEYS    2048            /* 11 bit code.            */
  1143.  
  1144. #define    METACH    0x1B            /* M- prefix,   Control-[, ESC    */
  1145. #define    CTMECH    0x1C            /* C-M- prefix, Control-\    */
  1146. #define    EXITCH    0x1D            /* Exit level,  Control-]    */
  1147. #define    CTRLCH    0x1E            /* C- prefix,    Control-^    */
  1148. #define    HELPCH    0x1F            /* Help key,    Control-_    */
  1149.  
  1150. #define    KCHAR    0x00FF            /* The basic character code.    */
  1151. #define    KCTRL    0x0100            /* Control flag.        */
  1152. #define    KMETA    0x0200            /* Meta flag.            */
  1153. #define    KCTLX    0x0400            /* Control-X flag.        */
  1154.  
  1155. #define    KFIRST    0x0080            /* First special.        */
  1156. #define    KLAST    0x009F            /* Last special.        */
  1157.  
  1158. #define    KRANDOM    0x0080            /* A "no key" code.        */
  1159. #define    K01    0x0081            /* Use these names to define    */
  1160. #define    K02    0x0082            /* the special keys on your    */
  1161. #define    K03    0x0083            /* terminal.            */
  1162. #define    K04    0x0084
  1163. #define    K05    0x0085
  1164. #define    K06    0x0086
  1165. #define    K07    0x0087
  1166. #define    K08    0x0088
  1167. #define    K09    0x0089
  1168. #define    K0A    0x008A
  1169. #define    K0B    0x008B
  1170. #define    K0C    0x008C
  1171. #define    K0D    0x008D
  1172. #define    K0E    0x008E
  1173. #define    K0F    0x008F
  1174. #define    K10    0x0090
  1175. #define    K11    0x0091
  1176. #define    K12    0x0092
  1177. #define    K13    0x0093
  1178. #define    K14    0x0094
  1179. #define    K15    0x0095
  1180. #define    K16    0x0096
  1181. #define    K17    0x0097
  1182. #define    K18    0x0098
  1183. #define    K19    0x0099
  1184. #define    K1A    0x009A
  1185. #define    K1B    0x009B
  1186. #define    K1C    0x009C
  1187. #define    K1D    0x009D
  1188. #define    K1E    0x009E
  1189. #define    K1F    0x009F
  1190.  
  1191. /*
  1192.  * These flags, and the macros below them,
  1193.  * make up a do-it-yourself set of "ctype" macros that
  1194.  * understand the DEC multinational set, and let me ask
  1195.  * a slightly different set of questions.
  1196.  */
  1197. #define    _W    0x01            /* Word.            */
  1198. #define    _U    0x02            /* Upper case letter.        */
  1199. #define    _L    0x04            /* Lower case letter.        */
  1200. #define    _C    0x08            /* Control.            */
  1201.  
  1202. #define    ISWORD(c)    ((cinfo[(c)]&_W)!=0)
  1203. #define    ISCTRL(c)    ((cinfo[(c)]&_C)!=0)
  1204. #define    ISUPPER(c)    ((cinfo[(c)]&_U)!=0)
  1205. #define    ISLOWER(c)    ((cinfo[(c)]&_L)!=0)
  1206. #define    TOUPPER(c)    ((c)-0x20)
  1207. #define    TOLOWER(c)    ((c)+0x20)
  1208.  
  1209. /*
  1210.  * The symbol table links editing functions
  1211.  * to names. Entries in the key map point at the symbol
  1212.  * table entry. A reference count is kept, but it is
  1213.  * probably next to useless right now. The old type code,
  1214.  * which was not being used and probably not right
  1215.  * anyway, is all gone.
  1216.  */
  1217. typedef    struct    SYMBOL {
  1218.     struct    SYMBOL *s_symp;        /* Hash chain.            */
  1219.     short    s_nkey;            /* Count of keys bound here.    */
  1220.     char    *s_name;        /* Name.            */
  1221.     int    (*s_funcp)();        /* Function.            */
  1222. }    SYMBOL;
  1223.  
  1224. /*
  1225.  * There is a window structure allocated for
  1226.  * every active display window. The windows are kept in a
  1227.  * big list, in top to bottom screen order, with the listhead at
  1228.  * "wheadp". Each window contains its own values of dot and mark.
  1229.  * The flag field contains some bits that are set by commands
  1230.  * to guide redisplay; although this is a bit of a compromise in
  1231.  * terms of decoupling, the full blown redisplay is just too
  1232.  * expensive to run for every input character. 
  1233.  */
  1234. typedef    struct    WINDOW {
  1235.     struct    WINDOW *w_wndp;        /* Next window            */
  1236.     struct    BUFFER *w_bufp;        /* Buffer displayed in window    */
  1237.     struct    LINE *w_linep;        /* Top line in the window    */
  1238.     struct    LINE *w_dotp;        /* Line containing "."        */
  1239.     short    w_doto;            /* Byte offset for "."        */
  1240.     struct    LINE *w_markp;        /* Line containing "mark"    */
  1241.     short    w_marko;        /* Byte offset for "mark"    */
  1242.     char    w_toprow;        /* Origin 0 top row of window    */
  1243.     char    w_ntrows;        /* # of rows of text in window    */
  1244.     char    w_force;        /* If NZ, forcing row.        */
  1245.     char    w_flag;            /* Flags.            */
  1246. }    WINDOW;
  1247.  
  1248. /*
  1249.  * Window flags are set by command processors to
  1250.  * tell the display system what has happened to the buffer
  1251.  * mapped by the window. Setting "WFHARD" is always a safe thing
  1252.  * to do, but it may do more work than is necessary. Always try
  1253.  * to set the simplest action that achieves the required update.
  1254.  * Because commands set bits in the "w_flag", update will see
  1255.  * all change flags, and do the most general one.
  1256.  */
  1257. #define    WFFORCE    0x01            /* Force reframe.        */
  1258. #define    WFMOVE    0x02            /* Movement from line to line.    */
  1259. #define    WFEDIT    0x04            /* Editing within a line.    */
  1260. #define    WFHARD    0x08            /* Better to a full display.    */
  1261. #define    WFMODE    0x10            /* Update mode line.        */
  1262.  
  1263. /*
  1264.  * Text is kept in buffers. A buffer header, described
  1265.  * below, exists for every buffer in the system. The buffers are
  1266.  * kept in a big list, so that commands that search for a buffer by
  1267.  * name can find the buffer header. There is a safe store for the
  1268.  * dot and mark in the header, but this is only valid if the buffer
  1269.  * is not being displayed (that is, if "b_nwnd" is 0). The text for
  1270.  * the buffer is kept in a circularly linked list of lines, with
  1271.  * a pointer to the header line in "b_linep".
  1272.  */
  1273. typedef    struct    BUFFER {
  1274.     struct    BUFFER *b_bufp;        /* Link to next BUFFER        */
  1275.     struct    LINE *b_dotp;        /* Link to "." LINE structure    */
  1276.     short    b_doto;            /* Offset of "." in above LINE    */
  1277.     struct    LINE *b_markp;        /* The same as the above two,    */
  1278.     short    b_marko;        /* but for the "mark"        */
  1279.     struct    LINE *b_linep;        /* Link to the header LINE    */
  1280.     char    b_nwnd;            /* Count of windows on buffer    */
  1281.     char    b_flag;            /* Flags            */
  1282.     char    b_fname[NFILEN];    /* File name            */
  1283.     char    b_bname[NBUFN];        /* Buffer name            */
  1284. }    BUFFER;
  1285.  
  1286. #define    BFCHG    0x01            /* Changed.            */
  1287. #define    BFBAK    0x02            /* Need to make a backup.    */
  1288.  
  1289. /*
  1290.  * This structure holds the starting position
  1291.  * (as a line/offset pair) and the number of characters in a
  1292.  * region of a buffer. This makes passing the specification
  1293.  * of a region around a little bit easier.
  1294.  * There have been some complaints that the short in this
  1295.  * structure is wrong; that a long would be more appropriate.
  1296.  * I'll awat more comments from the folks with the little
  1297.  * machines; I have a VAX, and everything fits.
  1298.  */
  1299. typedef    struct    {
  1300.     struct    LINE *r_linep;        /* Origin LINE address.        */
  1301.     short    r_offset;        /* Origin LINE offset.        */
  1302.     short    r_size;            /* Length in characters.    */
  1303. }    REGION;
  1304.  
  1305. /*
  1306.  * All text is kept in circularly linked
  1307.  * lists of "LINE" structures. These begin at the
  1308.  * header line (which is the blank line beyond the
  1309.  * end of the buffer). This line is pointed to by
  1310.  * the "BUFFER". Each line contains a the number of
  1311.  * bytes in the line (the "used" size), the size
  1312.  * of the text array, and the text. The end of line
  1313.  * is not stored as a byte; it's implied. Future
  1314.  * additions will include update hints, and a
  1315.  * list of marks into the line.
  1316.  */
  1317. typedef    struct    LINE {
  1318.     struct    LINE *l_fp;        /* Link to the next line    */
  1319.     struct    LINE *l_bp;        /* Link to the previous line    */
  1320.     short    l_size;            /* Allocated size        */
  1321.     short    l_used;            /* Used size            */
  1322. #if    PCC
  1323.     char    l_text[1];        /* A bunch of characters.    */
  1324. #else
  1325.     char    l_text[];        /* A bunch of characters.    */
  1326. #endif
  1327. }    LINE;
  1328.  
  1329. /*
  1330.  * The rationale behind these macros is that you
  1331.  * could (with some editing, like changing the type of a line
  1332.  * link from a "LINE *" to a "REFLINE", and fixing the commands
  1333.  * like file reading that break the rules) change the actual
  1334.  * storage representation of lines to use something fancy on
  1335.  * machines with small address spaces.
  1336.  */
  1337. #define    lforw(lp)    ((lp)->l_fp)
  1338. #define    lback(lp)    ((lp)->l_bp)
  1339. #define    lgetc(lp, n)    ((lp)->l_text[(n)]&0xFF)
  1340. #define    lputc(lp, n, c)    ((lp)->l_text[(n)]=(c))
  1341. #define    llength(lp)    ((lp)->l_used)
  1342.  
  1343. /*
  1344.  * Externals.
  1345.  */
  1346. extern    int    thisflag;
  1347. extern    int    lastflag;
  1348. extern    int    curgoal;
  1349. extern    int    epresf;
  1350. extern    int    sgarbf;
  1351. extern    WINDOW    *curwp;
  1352. extern    BUFFER    *curbp;
  1353. extern    WINDOW    *wheadp;
  1354. extern    BUFFER    *bheadp;
  1355. extern    BUFFER    *blistp;
  1356. extern    short    kbdm[];
  1357. extern    short    *kbdmip;
  1358. extern    short    *kbdmop;
  1359. extern    char    pat[];
  1360. extern    SYMBOL    *symbol[];
  1361. extern    SYMBOL    *binding[];
  1362. extern    BUFFER    *bfind();
  1363. extern    BUFFER    *bcreate();
  1364. extern    WINDOW    *wpopup();
  1365. extern    LINE    *lalloc();
  1366. extern  int    nrow;
  1367. extern  int    ncol;
  1368. extern    char    *version[];
  1369. extern    int    ttrow;
  1370. extern    int    ttcol;
  1371. extern    int    tceeol;
  1372. extern    int    tcinsl;
  1373. extern    int    tcdell;
  1374. extern    char    cinfo[];
  1375. extern    char    *keystrings[];
  1376. extern    SYMBOL    *symlookup();
  1377. extern    int    nmsg;
  1378. extern    int    curmsgf;
  1379. extern    int    newmsgf;
  1380. extern    char    msg[];
  1381.  
  1382. /*
  1383.  * Standard I/O.
  1384.  */
  1385. extern    char    *malloc();
  1386. extern    char    *strcpy();
  1387. extern    char    *strcat();
  1388. SHAR_EOF
  1389. if test 10999 -ne "`wc -c < 'def.h'`"
  1390. then
  1391.     echo shar: error transmitting "'def.h'" '(should have been 10999 characters)'
  1392. fi
  1393. fi
  1394. echo shar: extracting "'display.c'" '(19660 characters)'
  1395. if test -f 'display.c'
  1396. then
  1397.     echo shar: will not over-write existing file "'display.c'"
  1398. else
  1399. cat << \SHAR_EOF > 'display.c'
  1400. /*
  1401.  * Name:    MicroEMACS
  1402.  *        Gosling style redisplay.
  1403.  * Version:    30
  1404.  * Last edit:    10-Feb-86
  1405.  * By:        rex::conroy
  1406.  *        decvax!decwrl!dec-rhea!dec-rex!conroy
  1407.  *
  1408.  * The functions in this file handle redisplay. The
  1409.  * redisplay system knows almost nothing about the editing
  1410.  * process; the editing functions do, however, set some
  1411.  * hints to eliminate a lot of the grinding. There is more
  1412.  * that can be done; the "vtputc" interface is a real
  1413.  * pig. Two conditional compilation flags; the GOSLING
  1414.  * flag enables dynamic programming redisplay, using the
  1415.  * algorithm published by Jim Gosling in SIGOA. The MEMMAP
  1416.  * changes things around for memory mapped video. With
  1417.  * both off, the terminal is a VT52.
  1418.  */
  1419. #include    "def.h"
  1420.  
  1421. /*
  1422.  * You can change these back to the types
  1423.  * implied by the name if you get tight for space. If you
  1424.  * make both of them "int" you get better code on the VAX.
  1425.  * They do nothing if this is not Gosling redisplay, except
  1426.  * for change the size of a structure that isn't used.
  1427.  * A bit of a cheat.
  1428.  */
  1429. #define    XCHAR    int
  1430. #define    XSHORT    int
  1431.  
  1432. /*
  1433.  * A video structure always holds
  1434.  * an array of characters whose length is equal to
  1435.  * the longest line possible. Only some of this is
  1436.  * used if "ncol" isn't the same as "NCOL".
  1437.  */
  1438. typedef    struct    {
  1439.     short    v_hash;            /* Hash code, for compares.    */
  1440.     short    v_flag;            /* Flag word.            */
  1441.     short    v_color;        /* Color of the line.        */
  1442.     XSHORT    v_cost;            /* Cost of display.        */
  1443.     char    v_text[NCOL];        /* The actual characters.    */
  1444. }    VIDEO;
  1445.  
  1446. #define    VFCHG    0x0001            /* Changed.            */
  1447. #define    VFHBAD    0x0002            /* Hash and cost are bad.    */
  1448.  
  1449. /*
  1450.  * SCORE structures hold the optimal
  1451.  * trace trajectory, and the cost of redisplay, when
  1452.  * the dynamic programming redisplay code is used.
  1453.  * If no fancy redisplay, this isn't used. The trace index
  1454.  * fields can be "char", and the score a "short", but
  1455.  * this makes the code worse on the VAX.
  1456.  */
  1457. typedef    struct    {
  1458.     XCHAR    s_itrace;        /* "i" index for track back.    */
  1459.     XCHAR    s_jtrace;        /* "j" index for trace back.    */
  1460.     XSHORT    s_cost;            /* Display cost.        */
  1461. }    SCORE;
  1462.  
  1463. int    sgarbf    = TRUE;            /* TRUE if screen is garbage.    */
  1464. int    vtrow    = 0;            /* Virtual cursor row.        */
  1465. int    vtcol    = 0;            /* Virtual cursor column.    */
  1466. int    tthue    = CNONE;        /* Current color.        */
  1467. int    ttrow    = HUGE;            /* Physical cursor row.        */
  1468. int    ttcol    = HUGE;            /* Physical cursor column.    */
  1469. int    tttop    = HUGE;            /* Top of scroll region.    */
  1470. int    ttbot    = HUGE;            /* Bottom of scroll region.    */
  1471.  
  1472. VIDEO    *vscreen[NROW-1];        /* Edge vector, virtual.    */
  1473. VIDEO    *pscreen[NROW-1];        /* Edge vector, physical.    */
  1474. VIDEO    video[2*(NROW-1)];        /* Actual screen data.        */
  1475. VIDEO    blanks;                /* Blank line image.        */
  1476.  
  1477. #if    GOSLING
  1478. /*
  1479.  * This matrix is written as an array because
  1480.  * we do funny things in the "setscores" routine, which
  1481.  * is very compute intensive, to make the subscripts go away.
  1482.  * It would be "SCORE    score[NROW][NROW]" in old speak.
  1483.  * Look at "setscores" to understand what is up.
  1484.  */
  1485. SCORE    score[NROW*NROW];
  1486. #endif
  1487.  
  1488. /*
  1489.  * Initialize the data structures used
  1490.  * by the display code. The edge vectors used
  1491.  * to access the screens are set up. The operating
  1492.  * system's terminal I/O channel is set up. Fill the
  1493.  * "blanks" array with ASCII blanks. The rest is done
  1494.  * at compile time. The original window is marked
  1495.  * as needing full update, and the physical screen
  1496.  * is marked as garbage, so all the right stuff happens
  1497.  * on the first call to redisplay.
  1498.  */
  1499. vtinit()
  1500. {
  1501.     register VIDEO    *vp;
  1502.     register int    i;
  1503.  
  1504.     ttopen();
  1505.     ttinit();
  1506.     vp = &video[0];
  1507.     for (i=0; i<NROW-1; ++i) {
  1508.         vscreen[i] = vp;
  1509.         ++vp;
  1510.         pscreen[i] = vp;
  1511.         ++vp;
  1512.     }
  1513.     blanks.v_color = CTEXT;
  1514.     for (i=0; i<NCOL; ++i)
  1515.         blanks.v_text[i] = ' ';
  1516. }
  1517.  
  1518. /*
  1519.  * Tidy up the virtual display system
  1520.  * in anticipation of a return back to the host
  1521.  * operating system. Right now all we do is position
  1522.  * the cursor to the last line, erase the line, and
  1523.  * close the terminal channel.
  1524.  */
  1525. vttidy()
  1526. {
  1527.     ttcolor(CTEXT);
  1528.     ttnowindow();                /* No scroll window.    */
  1529.     ttmove(nrow-1, 0);            /* Echo line.        */
  1530.     tteeol();
  1531.     tttidy();
  1532.     ttflush();
  1533.     ttclose();
  1534. }
  1535.  
  1536. /*
  1537.  * Move the virtual cursor to an origin
  1538.  * 0 spot on the virtual display screen. I could
  1539.  * store the column as a character pointer to the spot
  1540.  * on the line, which would make "vtputc" a little bit
  1541.  * more efficient. No checking for errors.
  1542.  */
  1543. vtmove(row, col)
  1544. {
  1545.     vtrow = row;
  1546.     vtcol = col;
  1547. }
  1548.  
  1549. /*
  1550.  * Write a character to the virtual display,
  1551.  * dealing with long lines and the display of unprintable
  1552.  * things like control characters. Also expand tabs every 8
  1553.  * columns. This code only puts printing characters into 
  1554.  * the virtual display image. Special care must be taken when
  1555.  * expanding tabs. On a screen whose width is not a multiple
  1556.  * of 8, it is possible for the virtual cursor to hit the
  1557.  * right margin before the next tab stop is reached. This
  1558.  * makes the tab code loop if you are not careful.
  1559.  * Three guesses how we found this.
  1560.  */
  1561. vtputc(c)
  1562. register int    c;
  1563. {
  1564.     register VIDEO    *vp;
  1565.  
  1566.     vp = vscreen[vtrow];
  1567.     if (vtcol >= ncol)
  1568.         vp->v_text[ncol-1] = '$';
  1569.     else if (c == '\t') {
  1570.         do {
  1571.             vtputc(' ');
  1572.         } while (vtcol<ncol && (vtcol&0x07)!=0);
  1573.     } else if (ISCTRL(c) != FALSE) {
  1574.         vtputc('^');
  1575.         vtputc(c ^ 0x40);
  1576.     } else
  1577.         vp->v_text[vtcol++] = c;        
  1578. }
  1579.  
  1580. /*
  1581.  * Erase from the end of the
  1582.  * software cursor to the end of the
  1583.  * line on which the software cursor is
  1584.  * located. The display routines will decide
  1585.  * if a hardware erase to end of line command
  1586.  * should be used to display this.
  1587.  */
  1588. vteeol()
  1589. {
  1590.     register VIDEO    *vp;
  1591.  
  1592.     vp = vscreen[vtrow];
  1593.     while (vtcol < ncol)
  1594.         vp->v_text[vtcol++] = ' ';
  1595. }
  1596.  
  1597. /*
  1598.  * Make sure that the display is
  1599.  * right. This is a three part process. First,
  1600.  * scan through all of the windows looking for dirty
  1601.  * ones. Check the framing, and refresh the screen.
  1602.  * Second, make sure that "currow" and "curcol" are
  1603.  * correct for the current window. Third, make the
  1604.  * virtual and physical screens the same.
  1605.  */
  1606. update()
  1607. {
  1608.     register LINE    *lp;
  1609.     register WINDOW    *wp;
  1610.     register VIDEO    *vp1;
  1611.     register VIDEO    *vp2;
  1612.     register int    i;
  1613.     register int    j;
  1614.     register int    c;
  1615.     register int    hflag;
  1616.     register int    currow;
  1617.     register int    curcol;
  1618.     register int    offs;
  1619.     register int    size;
  1620.  
  1621.     if (curmsgf!=FALSE || newmsgf!=FALSE) {
  1622.         wp = wheadp;
  1623.         while (wp != NULL) {
  1624.             wp->w_flag |= WFMODE;    /* Must do mode lines.    */
  1625.             wp = wp->w_wndp;
  1626.         }
  1627.     }
  1628.     curmsgf = newmsgf;            /* Sync. up right now.    */
  1629.     hflag = FALSE;                /* Not hard.        */
  1630.     wp = wheadp;
  1631.     while (wp != NULL) {
  1632.         if (wp->w_flag != 0) {        /* Need update.        */
  1633.             if ((wp->w_flag&WFFORCE) == 0) {
  1634.                 lp = wp->w_linep;
  1635.                 for (i=0; i<wp->w_ntrows; ++i) {
  1636.                     if (lp == wp->w_dotp)
  1637.                         goto out;
  1638.                     if (lp == wp->w_bufp->b_linep)
  1639.                         break;
  1640.                     lp = lforw(lp);
  1641.                 }
  1642.             }
  1643.             i = wp->w_force;    /* Reframe this one.    */
  1644.             if (i > 0) {
  1645.                 --i;
  1646.                 if (i >= wp->w_ntrows)
  1647.                     i = wp->w_ntrows-1;
  1648.             } else if (i < 0) {
  1649.                 i += wp->w_ntrows;
  1650.                 if (i < 0)
  1651.                     i = 0;
  1652.             } else
  1653.                 i = wp->w_ntrows/2;
  1654.             lp = wp->w_dotp;
  1655.             while (i!=0 && lback(lp)!=wp->w_bufp->b_linep) {
  1656.                 --i;
  1657.                 lp = lback(lp);
  1658.             }
  1659.             wp->w_linep = lp;
  1660.             wp->w_flag |= WFHARD;    /* Force full.        */
  1661.         out:
  1662.             lp = wp->w_linep;    /* Try reduced update.    */
  1663.             i  = wp->w_toprow;
  1664.             if ((wp->w_flag&~WFMODE) == WFEDIT) {
  1665.                 while (lp != wp->w_dotp) {
  1666.                     ++i;
  1667.                     lp = lforw(lp);
  1668.                 }
  1669.                 vscreen[i]->v_color = CTEXT;
  1670.                 vscreen[i]->v_flag |= (VFCHG|VFHBAD);
  1671.                 vtmove(i, 0);
  1672.                 for (j=0; j<llength(lp); ++j)
  1673.                     vtputc(lgetc(lp, j));
  1674.                 vteeol();
  1675.             } else if ((wp->w_flag&(WFEDIT|WFHARD)) != 0) {
  1676.                 hflag = TRUE;
  1677.                 while (i < wp->w_toprow+wp->w_ntrows) {
  1678.                     vscreen[i]->v_color = CTEXT;
  1679.                     vscreen[i]->v_flag |= (VFCHG|VFHBAD);
  1680.                     vtmove(i, 0);
  1681.                     if (lp != wp->w_bufp->b_linep) {
  1682.                         for (j=0; j<llength(lp); ++j)
  1683.                             vtputc(lgetc(lp, j));
  1684.                         lp = lforw(lp);
  1685.                     }
  1686.                     vteeol();
  1687.                     ++i;
  1688.                 }
  1689.             }
  1690.             if ((wp->w_flag&WFMODE) != 0)
  1691.                 modeline(wp);
  1692.             wp->w_flag  = 0;
  1693.             wp->w_force = 0;
  1694.         }        
  1695.         wp = wp->w_wndp;
  1696.     }
  1697.     lp = curwp->w_linep;            /* Cursor location.    */
  1698.     currow = curwp->w_toprow;
  1699.     while (lp != curwp->w_dotp) {
  1700.         ++currow;
  1701.         lp = lforw(lp);
  1702.     }
  1703.     curcol = 0;
  1704.     i = 0;
  1705.     while (i < curwp->w_doto) {
  1706.         c = lgetc(lp, i++);
  1707.         if (c == '\t')
  1708.             curcol |= 0x07;
  1709.         else if (ISCTRL(c) != FALSE)
  1710.             ++curcol;
  1711.         ++curcol;
  1712.     }
  1713.     if (curcol >= ncol)            /* Long line.        */
  1714.         curcol = ncol-1;
  1715.     if (sgarbf != FALSE) {            /* Screen is garbage.    */
  1716.         sgarbf = FALSE;            /* Erase-page clears    */
  1717.         epresf = FALSE;            /* the message area.    */
  1718.         tttop  = HUGE;            /* Forget where you set    */
  1719.         ttbot  = HUGE;            /* scroll region.    */
  1720.         tthue  = CNONE;            /* Color unknown.    */
  1721.         ttmove(0, 0);
  1722.         tteeop();
  1723.         for (i=0; i<nrow-1; ++i) {
  1724.             uline(i, vscreen[i], &blanks);
  1725.             ucopy(vscreen[i], pscreen[i]);
  1726.         }
  1727.         ttmove(currow, curcol);
  1728.         ttflush();
  1729.         return;
  1730.     }
  1731. #if    GOSLING
  1732.     if (hflag != FALSE) {            /* Hard update?        */
  1733.         for (i=0; i<nrow-1; ++i) {    /* Compute hash data.    */
  1734.             hash(vscreen[i]);
  1735.             hash(pscreen[i]);
  1736.         }
  1737.         offs = 0;            /* Get top match.    */
  1738.         while (offs != nrow-1) {
  1739.             vp1 = vscreen[offs];
  1740.             vp2 = pscreen[offs];
  1741.             if (vp1->v_color != vp2->v_color
  1742.             ||  vp1->v_hash  != vp2->v_hash)
  1743.                 break;
  1744.             uline(offs, vp1, vp2);
  1745.             ucopy(vp1, vp2);
  1746.             ++offs;
  1747.         }
  1748.         if (offs == nrow-1) {        /* Might get it all.    */
  1749.             ttmove(currow, curcol);
  1750.             ttflush();
  1751.             return;
  1752.         }
  1753.         size = nrow-1;            /* Get bottom match.    */
  1754.         while (size != offs) {
  1755.             vp1 = vscreen[size-1];
  1756.             vp2 = pscreen[size-1];
  1757.             if (vp1->v_color != vp2->v_color
  1758.             ||  vp1->v_hash  != vp2->v_hash)
  1759.                 break;
  1760.             uline(size-1, vp1, vp2);
  1761.             ucopy(vp1, vp2);
  1762.             --size;
  1763.         }
  1764.         if ((size -= offs) == 0)    /* Get screen size.    */
  1765.             abort();
  1766.         setscores(offs, size);        /* Do hard update.    */
  1767.         traceback(offs, size, size, size);
  1768.         for (i=0; i<size; ++i)
  1769.             ucopy(vscreen[offs+i], pscreen[offs+i]);
  1770.         ttmove(currow, curcol);
  1771.         ttflush();
  1772.         return;            
  1773.     }
  1774. #endif
  1775.     for (i=0; i<nrow-1; ++i) {        /* Easy update.        */
  1776.         vp1 = vscreen[i];
  1777.         vp2 = pscreen[i];
  1778.         if ((vp1->v_flag&VFCHG) != 0) {
  1779.             uline(i, vp1, vp2);
  1780.             ucopy(vp1, vp2);
  1781.         }
  1782.     }
  1783.     ttmove(currow, curcol);
  1784.     ttflush();
  1785. }
  1786.  
  1787. /*
  1788.  * Update a saved copy of a line,
  1789.  * kept in a VIDEO structure. The "vvp" is
  1790.  * the one in the "vscreen". The "pvp" is the one
  1791.  * in the "pscreen". This is called to make the
  1792.  * virtual and physical screens the same when
  1793.  * display has done an update.
  1794.  */
  1795. ucopy(vvp, pvp)
  1796. register VIDEO    *vvp;
  1797. register VIDEO    *pvp;
  1798. {
  1799.     register int    i;
  1800.  
  1801.     vvp->v_flag &= ~VFCHG;            /* Changes done.    */
  1802.     pvp->v_flag  = vvp->v_flag;        /* Update model.    */
  1803.     pvp->v_hash  = vvp->v_hash;
  1804.     pvp->v_cost  = vvp->v_cost;
  1805.     pvp->v_color = vvp->v_color;
  1806.     for (i=0; i<ncol; ++i)
  1807.         pvp->v_text[i] = vvp->v_text[i];
  1808. }
  1809.  
  1810. /*
  1811.  * Update a single line. This routine only
  1812.  * uses basic functionality (no insert and delete character,
  1813.  * but erase to end of line). The "vvp" points at the VIDEO
  1814.  * structure for the line on the virtual screen, and the "pvp"
  1815.  * is the same for the physical screen. Avoid erase to end of
  1816.  * line when updating CMODE color lines, because of the way that
  1817.  * reverse video works on most terminals.
  1818.  */
  1819. uline(row, vvp, pvp)
  1820. VIDEO    *vvp;
  1821. VIDEO    *pvp;
  1822. {
  1823. #if    MEMMAP
  1824.     putline(row+1, 1, &vvp->v_text[0]);
  1825. #else
  1826.     register char    *cp1;
  1827.     register char    *cp2;
  1828.     register char    *cp3;
  1829.     register char    *cp4;
  1830.     register char    *cp5;
  1831.     register int    nbflag;
  1832.  
  1833.     if (vvp->v_color != pvp->v_color) {    /* Wrong color, do a    */
  1834.         ttmove(row, 0);            /* full redraw.        */
  1835.         ttcolor(vvp->v_color);
  1836.         cp1 = &vvp->v_text[0];
  1837.         cp2 = &vvp->v_text[ncol];
  1838.         while (cp1 != cp2) {
  1839.             ttputc(*cp1++);
  1840.             ++ttcol;
  1841.         }
  1842.         return;
  1843.     }
  1844.     cp1 = &vvp->v_text[0];            /* Compute left match.    */
  1845.     cp2 = &pvp->v_text[0];
  1846.     while (cp1!=&vvp->v_text[ncol] && cp1[0]==cp2[0]) {
  1847.         ++cp1;
  1848.         ++cp2;
  1849.     }
  1850.     if (cp1 == &vvp->v_text[ncol])        /* All equal.        */
  1851.         return;
  1852.     nbflag = FALSE;
  1853.     cp3 = &vvp->v_text[ncol];        /* Compute right match.    */
  1854.     cp4 = &pvp->v_text[ncol];
  1855.     while (cp3[-1] == cp4[-1]) {
  1856.         --cp3;
  1857.         --cp4;
  1858.         if (cp3[0] != ' ')        /* Note non-blanks in    */
  1859.             nbflag = TRUE;        /* the right match.    */
  1860.     }
  1861.     cp5 = cp3;                /* Is erase good?    */
  1862.     if (nbflag==FALSE && vvp->v_color==CTEXT) {
  1863.         while (cp5!=cp1 && cp5[-1]==' ')
  1864.             --cp5;
  1865.         /* Alcyon hack */
  1866.         if ((int)(cp3-cp5) <= tceeol)
  1867.             cp5 = cp3;
  1868.     }
  1869.     /* Alcyon hack */
  1870.     ttmove(row, (int)(cp1-&vvp->v_text[0]));
  1871.     ttcolor(vvp->v_color);
  1872.     while (cp1 != cp5) {
  1873.         ttputc(*cp1++);
  1874.         ++ttcol;
  1875.     }
  1876.     if (cp5 != cp3)                /* Do erase.        */
  1877.         tteeol();
  1878. #endif
  1879. }
  1880.  
  1881. /*
  1882.  * Redisplay the mode line for
  1883.  * the window pointed to by the "wp".
  1884.  * This is the only routine that has any idea
  1885.  * of how the modeline is formatted. You can
  1886.  * change the modeline format by hacking at
  1887.  * this routine. Called by "update" any time
  1888.  * there is a dirty window.
  1889.  */
  1890. modeline(wp)
  1891. register WINDOW    *wp;
  1892. {
  1893.     register char    *cp;
  1894.     register int    c;
  1895.     register int    n;
  1896.     register BUFFER    *bp;
  1897.  
  1898.     n = wp->w_toprow+wp->w_ntrows;        /* Location.        */
  1899.     vscreen[n]->v_color = CMODE;        /* Mode line color.    */
  1900.     vscreen[n]->v_flag |= (VFCHG|VFHBAD);    /* Recompute, display.    */
  1901.     vtmove(n, 0);                /* Seek to right line.    */
  1902.     bp = wp->w_bufp;
  1903.     if ((bp->b_flag&BFCHG) != 0)        /* "*" if changed.    */
  1904.         vtputc('*');
  1905.     else
  1906.         vtputc(' ');
  1907.     n  = 1;
  1908.     cp = "MicroEMACS";            /* Buffer name.        */
  1909.     while ((c = *cp++) != 0) {
  1910.         vtputc(c);
  1911.         ++n;
  1912.     }
  1913.     if (bp->b_bname[0] != 0) {
  1914.         vtputc(' ');
  1915.         ++n;
  1916.         cp = &bp->b_bname[0];
  1917.         while ((c = *cp++) != 0) {
  1918.             vtputc(c);
  1919.             ++n;
  1920.         }
  1921.     }
  1922.     if (bp->b_fname[0] != 0) {        /* File name.        */
  1923.         vtputc(' ');
  1924.         ++n;
  1925.         cp = "File:";
  1926.         while ((c = *cp++) != 0) {
  1927.             vtputc(c);
  1928.             ++n;
  1929.         }
  1930.         cp = &bp->b_fname[0];
  1931.         while ((c = *cp++) != 0) {
  1932.             vtputc(c);
  1933.             ++n;
  1934.         }
  1935.     }
  1936.     if (curmsgf != FALSE            /* Message alert.    */
  1937.     && wp->w_wndp == NULL) {
  1938.         while (n < ncol-5-1) {
  1939.             vtputc(' ');
  1940.             ++n;
  1941.         }
  1942.         cp = "[Msg]";            /* Sizeof("[Msg]") = 5.    */
  1943.         while ((c = *cp++) != 0) {
  1944.             vtputc(c);
  1945.             ++n;
  1946.         }
  1947.     }
  1948.     while (n < ncol) {            /* Pad out.        */
  1949.         vtputc(' ');
  1950.         ++n;
  1951.     }
  1952. }
  1953.  
  1954. #if    GOSLING
  1955. /*
  1956.  * Compute the hash code for
  1957.  * the line pointed to by the "vp". Recompute
  1958.  * it if necessary. Also set the approximate redisplay
  1959.  * cost. The validity of the hash code is marked by
  1960.  * a flag bit. The cost understand the advantages
  1961.  * of erase to end of line. Tuned for the VAX
  1962.  * by Bob McNamara; better than it used to be on
  1963.  * just about any machine.
  1964.  */
  1965. hash(vp)
  1966. register VIDEO    *vp;
  1967. {
  1968.     register int    i;
  1969.     register int    n;
  1970.     register char    *s;
  1971.  
  1972.     if ((vp->v_flag&VFHBAD) != 0) {        /* Hash bad.        */
  1973.         s = &vp->v_text[ncol-1];
  1974.         for (i=ncol; i!=0; --i, --s)
  1975.             if (*s != ' ')
  1976.                 break;
  1977.         n = ncol-i;            /* Erase cheaper?    */
  1978.         if (n > tceeol)
  1979.             n = tceeol;
  1980.         vp->v_cost = i+n;        /* Bytes + blanks.    */
  1981.         for (n=0; i!=0; --i, --s)
  1982.             n = (n<<5) + n + *s;
  1983.         vp->v_hash = n;            /* Hash code.        */
  1984.         vp->v_flag &= ~VFHBAD;        /* Flag as all done.    */
  1985.     }
  1986. }
  1987.  
  1988. /*
  1989.  * Compute the Insert-Delete
  1990.  * cost matrix. The dynamic programming algorithm
  1991.  * described by James Gosling is used. This code assumes
  1992.  * that the line above the echo line is the last line involved
  1993.  * in the scroll region. This is easy to arrange on the VT100
  1994.  * because of the scrolling region. The "offs" is the origin 0
  1995.  * offset of the first row in the virtual/physical screen that
  1996.  * is being updated; the "size" is the length of the chunk of
  1997.  * screen being updated. For a full screen update, use offs=0
  1998.  * and size=nrow-1.
  1999.  *
  2000.  * Older versions of this code implemented the score matrix by
  2001.  * a two dimensional array of SCORE nodes. This put all kinds of
  2002.  * multiply instructions in the code! This version is written to
  2003.  * use a linear array and pointers, and contains no multiplication
  2004.  * at all. The code has been carefully looked at on the VAX, with
  2005.  * only marginal checking on other machines for efficiency. In
  2006.  * fact, this has been tuned twice! Bob McNamara tuned it even
  2007.  * more for the VAX, which is a big issue for him because of
  2008.  * the 66 line X displays.
  2009.  *
  2010.  * On some machines, replacing the "for (i=1; i<=size; ++i)" with
  2011.  * i = 1; do { } while (++i <=size)" will make the code quite a
  2012.  * bit better; but it looks ugly.
  2013.  */
  2014. setscores(offs, size)
  2015. {
  2016.     register SCORE    *sp;
  2017.     register int    tempcost;
  2018.     register int    bestcost;
  2019.     register int    j;
  2020.     register int    i;
  2021.     register VIDEO    **vp;
  2022.     register VIDEO    **pp;
  2023.     register SCORE    *sp1;
  2024.     register VIDEO    **vbase;
  2025.     register VIDEO    **pbase;
  2026.  
  2027.     vbase = &vscreen[offs-1];        /* By hand CSE's.    */
  2028.     pbase = &pscreen[offs-1];
  2029.     score[0].s_itrace = 0;            /* [0, 0]        */
  2030.     score[0].s_jtrace = 0;
  2031.     score[0].s_cost   = 0;
  2032.     sp = &score[1];                /* Row 0, inserts.    */
  2033.     tempcost = 0;
  2034.     vp = &vbase[1];
  2035.     for (j=1; j<=size; ++j) {
  2036.         sp->s_itrace = 0;
  2037.         sp->s_jtrace = j-1;
  2038.         tempcost += tcinsl;
  2039.         tempcost += (*vp)->v_cost;
  2040.         sp->s_cost = tempcost;
  2041.         ++vp;
  2042.         ++sp;
  2043.     }
  2044.     sp = &score[NROW];            /* Column 0, deletes.    */
  2045.     tempcost = 0;
  2046.     for (i=1; i<=size; ++i) {
  2047.         sp->s_itrace = i-1;
  2048.         sp->s_jtrace = 0;
  2049.         tempcost  += tcdell;
  2050.         sp->s_cost = tempcost;
  2051.         sp += NROW;
  2052.     }
  2053.     sp1 = &score[NROW+1];            /* [1, 1].        */
  2054.     pp = &pbase[1];
  2055.     for (i=1; i<=size; ++i) {
  2056.         sp = sp1;
  2057.         vp = &vbase[1];
  2058.         for (j=1; j<=size; ++j) {
  2059.             sp->s_itrace = i-1;
  2060.             sp->s_jtrace = j;
  2061.             bestcost = (sp-NROW)->s_cost;
  2062.             if (j != size)        /* Cd(A[i])=0 @ Dis.    */
  2063.                 bestcost += tcdell;
  2064.             tempcost = (sp-1)->s_cost;
  2065.             tempcost += (*vp)->v_cost;
  2066.             if (i != size)        /* Ci(B[j])=0 @ Dsj.    */
  2067.                 tempcost += tcinsl;
  2068.             if (tempcost < bestcost) {
  2069.                 sp->s_itrace = i;
  2070.                 sp->s_jtrace = j-1;
  2071.                 bestcost = tempcost;
  2072.             }
  2073.             tempcost = (sp-NROW-1)->s_cost;
  2074.             if ((*pp)->v_color != (*vp)->v_color
  2075.             ||  (*pp)->v_hash  != (*vp)->v_hash)
  2076.                 tempcost += (*vp)->v_cost;
  2077.             if (tempcost < bestcost) {
  2078.                 sp->s_itrace = i-1;
  2079.                 sp->s_jtrace = j-1;
  2080.                 bestcost = tempcost;
  2081.             }
  2082.             sp->s_cost = bestcost;
  2083.             ++sp;            /* Next column.        */
  2084.             ++vp;
  2085.         }
  2086.         ++pp;
  2087.         sp1 += NROW;            /* Next row.        */
  2088.     }
  2089. }
  2090.  
  2091. /*
  2092.  * Trace back through the dynamic programming cost
  2093.  * matrix, and update the screen using an optimal sequence
  2094.  * of redraws, insert lines, and delete lines. The "offs" is
  2095.  * the origin 0 offset of the chunk of the screen we are about to
  2096.  * update. The "i" and "j" are always started in the lower right
  2097.  * corner of the matrix, and imply the size of the screen.
  2098.  * A full screen traceback is called with offs=0 and i=j=nrow-1.
  2099.  * There is some do-it-yourself double subscripting here,
  2100.  * which is acceptable because this routine is much less compute
  2101.  * intensive then the code that builds the score matrix!
  2102.  */
  2103. traceback(offs, size, i, j)
  2104. {
  2105.     register int    itrace;
  2106.     register int    jtrace;
  2107.     register int    k;
  2108.     register int    ninsl;
  2109.     register int    ndraw;
  2110.     register int    ndell;
  2111.  
  2112.     if (i==0 && j==0)            /* End of update.    */
  2113.         return;
  2114.     itrace = score[(NROW*i) + j].s_itrace;
  2115.     jtrace = score[(NROW*i) + j].s_jtrace;
  2116.     if (itrace == i) {            /* [i, j-1]        */
  2117.         ninsl = 0;            /* Collect inserts.    */
  2118.         if (i != size)
  2119.             ninsl = 1;
  2120.         ndraw = 1;
  2121.         while (itrace!=0 || jtrace!=0) {
  2122.             if (score[(NROW*itrace) + jtrace].s_itrace != itrace)
  2123.                 break;
  2124.             jtrace = score[(NROW*itrace) + jtrace].s_jtrace;
  2125.             if (i != size)
  2126.                 ++ninsl;
  2127.             ++ndraw;
  2128.         }
  2129.         traceback(offs, size, itrace, jtrace);
  2130.         if (ninsl != 0) {
  2131.             ttcolor(CTEXT);
  2132.             ttinsl(offs+j-ninsl, offs+size-1, ninsl);
  2133.         }
  2134.         do {                /* B[j], A[j] blank.    */
  2135.             k = offs+j-ndraw;
  2136.             uline(k, vscreen[k], &blanks);
  2137.         } while (--ndraw);
  2138.         return;
  2139.     }
  2140.     if (jtrace == j) {            /* [i-1, j]        */
  2141.         ndell = 0;            /* Collect deletes.    */
  2142.         if (j != size)
  2143.             ndell = 1;
  2144.         while (itrace!=0 || jtrace!=0) {
  2145.             if (score[(NROW*itrace) + jtrace].s_jtrace != jtrace)
  2146.                 break;
  2147.             itrace = score[(NROW*itrace) + jtrace].s_itrace;
  2148.             if (j != size)
  2149.                 ++ndell;
  2150.         }
  2151.         if (ndell != 0) {
  2152.             ttcolor(CTEXT);
  2153.             ttdell(offs+i-ndell, offs+size-1, ndell);
  2154.         }
  2155.         traceback(offs, size, itrace, jtrace);
  2156.         return;
  2157.     }
  2158.     traceback(offs, size, itrace, jtrace);
  2159.     k = offs+j-1;
  2160.     uline(k, vscreen[k], pscreen[offs+i-1]);
  2161. }
  2162. #endif
  2163. SHAR_EOF
  2164. if test 19660 -ne "`wc -c < 'display.c'`"
  2165. then
  2166.     echo shar: error transmitting "'display.c'" '(should have been 19660 characters)'
  2167. fi
  2168. fi
  2169. exit 0
  2170. #    End of shell archive
  2171.